package com.wocai.jrt.task;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vteba.utils.id.ObjectId;
import com.wocai.jrt.customer.model.Customer;
import com.wocai.jrt.customer.service.spi.CustomerService;
import com.wocai.jrt.employee.model.Employee;
import com.wocai.jrt.employee.service.spi.EmployeeService;
import com.wocai.jrt.investor.model.Investor;
import com.wocai.jrt.investor.service.spi.InvestorService;
import com.wocai.jrt.message.model.MessageLog;
import com.wocai.jrt.message.service.spi.MessageLogService;
import com.wocai.jrt.orders.bean.OrderStateResBean;
import com.wocai.jrt.orders.dao.AppointmentDao;
import com.wocai.jrt.orders.dao.OrdersDao;
import com.wocai.jrt.orders.model.Appointment;
import com.wocai.jrt.orders.model.Orders;
import com.wocai.jrt.orders.model.OrdersBean;
import com.wocai.jrt.orders.service.spi.AppointmentService;
import com.wocai.jrt.orders.service.spi.OrdersService;
import com.wocai.jrt.product.dao.ProductDao;
import com.wocai.jrt.product.model.Product;
import com.wocai.jrt.product.service.spi.ProductService;
import com.wocai.jrt.utils.MessagePush;
import com.wocai.jrt.utils.MyDateUtils;
import com.wocai.jrt.utils.SmsUtils;

/**
 * 预约单相关的service业务实现。
 * @author zhangyz
 * @date 2015-8-17 14:27:16
 */
@Named
public class QuartzTaskServiceImpl   {
	
	
	private static final Logger LOGGER = LoggerFactory.getLogger(QuartzTaskServiceImpl.class);
	
	private static final int STATE_EXPIRE = 7;
	private static final int STATE_BECASHED = 8;
	
	@Inject
	private AppointmentDao appointmentDao;
	@Inject
	private AppointmentService appointmentServiceImpl;
	@Inject
	private InvestorService investorServiceImpl;
	@Inject
	private ProductService productServiceImpl;
	@Inject
	private MessageLogService messageLogServiceImpl;
	@Inject
	private EmployeeService employeeServiceImpl;
	@Inject
	private ProductDao productDao;
	@Inject
	private OrdersService ordersServiceImpl;
	@Inject
	private CustomerService customerServiceImpl;
	@Inject
	private OrdersDao ordersDao;
	
	//消息推送功能部分
	/**
	 * 定时任务:产品募集第一天向所有可售卖该产品的理财师 消息推送和短信推送
	 * 每日7点执行一次
	 */
	public void productTask(){
		try {
			Product product = new Product();
			product.setState(0);
			//获取系统下所有即将上线的产品
			List<Product> proList = productServiceImpl.pagedList(product);
			DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
			String curDate = df.format(new Date());
			NumberFormat nf = new DecimalFormat("####.##");
			for (Product pro : proList) {
				//获取当前机构下可售所有产品的团队下的所有理财师
				String orgId = pro.getOrgId();
				List<Employee> sellAllEmpList = productDao.getSellAllProductEmps(orgId);
				String recruitStartTime = df.format(pro.getRecruitStartTime());
				if (curDate.equals(recruitStartTime)) {
					//获取可售该产品的理财师
					String productId = pro.getId();
					List<Employee> sellAppointempList =  productDao.getSellAppointProEmps(productId);
					String msg = pro.getBriefName()+" 今日开放募集,募集规模为"+nf.format(pro.getScale())+" 元";
					Set<String> alias = new HashSet<String>();
					for (Employee emp : sellAllEmpList) {
						alias.add(emp.getEmployeeId());
						//向可售卖该产品的理财师发送短信
						String res = SmsUtils.send(emp.getMobile(),msg);
						LOGGER.info("SmsUtils send productTask message for employee [{}] result :"+res.toString(),emp.getMobile());
					}
					for (Employee emp : sellAppointempList) {
						alias.add(emp.getEmployeeId());
						//向所有可售卖该产品的理财师发送短信
						String res = SmsUtils.send(emp.getMobile(),msg);
						LOGGER.info("SmsUtils send productTask message for employee [{}] result :"+res.toString(),emp.getMobile());
					}
					List<MessageLog> messageLogList = new ArrayList<MessageLog>();
					//向所有可售卖该产品的理财师发送消息
					for (String id : alias) {
						MessageLog message = new MessageLog();
		 				message.setId(ObjectId.get().toString());
		 				message.setEmployeeId(id);
		 				message.setSender("机构消息");
		 				message.setSource("机构后台");
		 				message.setSkipType(4);
		 				message.setSkipKey(productId);
		 				message.setType(2);
		 				message.setState(0);
		 				message.setOrgId(orgId);
		 				message.setMessageType(1);
		 				Date date = new Date();
		 				message.setCreateTime(date);
		 				message.setSendTime(date);
		 				message.setMessage(msg);
		 				messageLogList.add(message);
					}
					//批量保存消息日志
	 				int result = messageLogServiceImpl.msgLogInsertBatch(messageLogList);
				    int size = messageLogList.size();
		            if (size == result  ) {
		                LOGGER.info("save message for productTask success");
					}else if (size < result && result != 0) {
		                LOGGER.info("save part message for productTask success");
					}else{
		                LOGGER.info("save message for productTask error ");
					}
	 				//向所有可售卖该产品的理财师发送消息
	     			MessagePush messagePush = new MessagePush(msg,"机构消息");
	     			messagePush.sendPushAlias(alias);
				}
			}
		} catch (Exception e) {
			LOGGER.info("productTask execute error: "+ e.getMessage());
		}
	}
	
	 /**
	 * 定时任务:距预约时间还有1小时提醒理财师
	 * 每隔10分钟执行一次
	 */
	public void appointmentTask(){
		try {
			//获取系统下所有未处理的预约单
			Appointment appointment = new Appointment();
			appointment.setState(0);
			List<Appointment> appoList = appointmentDao.unDealList(appointment);//unDealList(appointment);
			DateFormat df = new SimpleDateFormat("HH:mm");
			Date nowDate = new Date();
			for (Appointment  appo: appoList) {
				Date appoTime = appo.getAppointTime();
				if (appoTime != null) {
					Double diff = (appoTime.getTime()-nowDate.getTime())/3600000D;
					//距离预约时间还有大约1小时时提醒理财师
					if(diff< 1.16667D  && appo.getRemind() == false ){
						Investor investor  = investorServiceImpl.get(appo.getInvestorId());
						Employee emp = employeeServiceImpl.get(appo.getEmployeeId());
						if (investor == null || emp == null) {
							LOGGER.error("save message for appointmentTask error due to param is not compeletly");
							continue;
						}
						//向理财师推送消息
						MessageLog message = new MessageLog();
		 				message.setId(ObjectId.get().toString());
		 				message.setEmployeeId(appo.getEmployeeId());
		 				message.setSender("机构消息");
		 				message.setSource("机构后台");
		 				message.setSkipType(2);
		 				message.setSkipKey(appo.getId());
		 				message.setType(2);
		 				message.setState(0);
		 				message.setMessageType(2);
		 				message.setOrgId(appo.getOrgId());
		 				Date date = new Date();
		 				message.setCreateTime(date);
		 				message.setSendTime(date);
		 				String msg ="您 "+df.format(appo.getAppointTime())+" 预约了投资人 "+investor.getName()+",离预约时间大约还有1小时。";
		 				message.setMessage(msg);
		 				//保存消息日志
		 				int result = messageLogServiceImpl.save(message);
		 				if(result == 1){
		 					LOGGER.error("save message for appointmentTask success");
		 				}else{
		 					LOGGER.error("save message for appointmentTask error");
		 					continue;
		 				}
		 				//更新预约单提醒状态
		 				Appointment tempAppo = new Appointment();
		 				tempAppo.setRemind(true);
		 				tempAppo.setId(appo.getId());
		 				appointmentServiceImpl.updateById(tempAppo);
		    			//向机构员工pad端发送预约分配消息
		     			MessagePush messagePush = new MessagePush(msg,"机构消息");
		     			Set<String> alias = new HashSet<String>();
		     			alias.add(appo.getEmployeeId());
		     			messagePush.sendPushAlias(alias);
		     			//向接收人发送短信
			    		String res = SmsUtils.send(emp.getMobile(),msg);
			    		LOGGER.info("SmsUtils send appointmentTask message for employee [{}] result :"+res.toString(),emp.getMobile());
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			LOGGER.info("appointmentTask execute error: "+ e.getMessage());
		}
	}
	
	 /**
	 * 定时任务:订单兑付到期当天短信通知投资人,Pad端提前一天通知理财师和投后app用户
	 * 每日8点执行一次
	 */
	public void orderMaturityTask(){
		try {
			//获取订单状态为：6已完成 或者 7 即将到期的订单
			OrdersBean ordersBean = new OrdersBean();
			List<Integer> stateList = new ArrayList<Integer>();
			stateList.add(6);
			stateList.add(7);
			ordersBean.createCriteria().andStateIn(stateList);
			List<Orders> list = ordersServiceImpl.pagedForList(ordersBean);
			for (Orders orders : list) {
				//剔除删除状态的订单
				if(!orders.getDeleted()){
					 Product product = productDao.get(orders.getProductId());
					 if(product == null){
						 LOGGER.info("execute orderMaturityTask error due to product is null");
						 continue;
					 }
					 Integer Duration = product.getDuration();
					 Date payTime = product.getSetupTime();//注意：此处需要改成产品的基金成立时间 之前是用的订单支付时间orders.getPayTime();
					 if(Duration != null&&payTime!=null){
						 Date today = new Date();
						 Date maturityDate =DateUtils.addMonths(payTime,Duration);
						 Date maturityDateBefore =DateUtils.addDays(maturityDate, -1);
						 String employeeId = orders.getEmployeeId();
						 Investor investor  = investorServiceImpl.get(orders.getInvestorId());
						 Employee emp = employeeServiceImpl.get(orders.getEmployeeId());
						 //到期兑付前一天通知理财师,向投后APP用户推送消息
						 if(DateUtils.isSameDay(maturityDateBefore,today)){
						    if (investor == null || emp == null) {
								LOGGER.error("save message for orderMaturityTask error due to param is not compeletly");
								continue;
							}
			    			//向理财师推送消息
							MessageLog message = new MessageLog();
			 				message.setId(ObjectId.get().toString());
			 				message.setEmployeeId(employeeId);
			 				message.setSender("机构消息");
			 				message.setSource("机构后台");
			 				message.setType(2);
			 				message.setState(0);
			 				message.setMessageType(1);
			 				message.setSkipKey(orders.getOrderId());
			 				message.setSkipType(1);
			 				message.setOrgId(orders.getOrgId());
			 				Date date = new Date();
			 				message.setCreateTime(date);
			 				message.setSendTime(date);
			 				String msgEmp ="您的投资人"+investor.getName()+",购买的产品"+product.getBriefName()+"已经到期，请联系进行兑付。";
			 				message.setMessage(msgEmp);
			 				//保存消息日志
			 				int result = messageLogServiceImpl.save(message);
			 				if(result == 1){
			 					LOGGER.info("save message for employee orderMaturityTask success");
			 				}else{
			 					LOGGER.error("save message for employee orderMaturityTask error");
			 					continue;
			 				}
							//向机构理财师pad端发送到期兑付提醒投资人消息
			     			MessagePush messagePush = new MessagePush(msgEmp,"机构消息");
			     			Set<String> alias = new HashSet<String>();
			     			alias.add(employeeId);
			     			messagePush.sendPushAlias(alias);
			     			//向理财师发送到期兑付提醒投资人短信
			     			String res = SmsUtils.send(emp.getMobile(),msgEmp);
				    		LOGGER.info("SmsUtils send orderMaturityTask message for employee [{}] result :"+res.toString(),emp.getMobile());
				    		//向投后APP用户推送消息
				    		Customer customer = new Customer();
							customer.setMobile(investor.getMobile());
							List<Customer> cusListTmp = customerServiceImpl.pagedList(customer);
							if(cusListTmp.size() == 1){
								Customer cus = cusListTmp.get(0);
								MessageLog msgLog = new MessageLog();
								msgLog.setId(ObjectId.get().toString());
								msgLog.setCustomerId(cus.getId());
								msgLog.setBusinessType(2);
								msgLog.setType(3);
								msgLog.setState(0);
								msgLog.setCreateTime(date);
								msgLog.setSource("机构后台");
								msgLog.setSender("投后消息");
								msgLog.setSkipKey(orders.getOrderId());
								msgLog.setSkipType(1);
								msgLog.setOrgId(orders.getOrgId());
					    		String cusMsgEmp ="尊敬的"+investor.getName()+"，您购买的"+product.getBriefName()+"将于"+DateFormatUtils.format(maturityDate, "yyyy-MM-dd")+"到期，点击查看详情";
					    		msgLog.setMessage(cusMsgEmp);
					    		//保存投后用户消息日志
				 				int s = messageLogServiceImpl.save(msgLog);
				 				if(s == 1){
				 					LOGGER.error("save message for customer orderMaturityTask success");
				 				}else{
				 					LOGGER.error("save message for customer orderMaturityTask error");
				 					continue;
				 				}
				 				//向投后APP用户发送推送消息  (别名为投后用户id,组别为机构id) 
					    		MessagePush messageCusPush = new MessagePush(cusMsgEmp,"投后消息",messageLogServiceImpl.getUnReadNum(investor.getOrgId(), cus.getId()));
				     			messageCusPush.sendCusPushTag(investor.getOrgId(),cus.getId());
							}
						 }
						 //当天短信通知投资人
						 if(DateUtils.isSameDay(maturityDate, today)){
							//向投资人发送到期兑付提醒短信
						   String msg = "您购买的产品"+product.getBriefName()+",今天到期，请联系您的理财师"+emp.getName()+"（手机"+emp.getMobile()+"）进行兑付"; 
	                       String result = SmsUtils.send(investor.getMobile(),msg);
	                       LOGGER.info("SmsUtils send orderMaturityTask message for investor [{}] result :"+result.toString(),investor.getMobile());
						 }
					 }
				}
			}
		} catch (Exception e) {
			LOGGER.info("orderMaturityTask execute error: "+ e.getMessage());
		}
	}
	 
	 /**
	 * 定时任务: 1、投资人生日短信通知。理财师会收到Pad端通知,投后APP用户收到推送消息 2、投资人测评状态更新  投资人测评时间超过一年,测评状态修改为未测评
	 * 每日8点10分执行一次
	 */
	public String investorBirthTask(){
		try {
			Investor investor = new Investor();
			List<Investor> list =investorServiceImpl.pagedList(investor);
			String nowStr = DateFormatUtils.format(new Date(), "MM-dd");
			Date today = new Date();
			for (Investor inves : list) {
				Date birthday = inves.getBirthday();
				if (birthday == null) {
					continue;
				}
				String brith = DateFormatUtils.format(birthday, "MM-dd");
				if(nowStr.equals(brith)){
					String msg = "尊敬的"+inves.getName()+"(女士/先生），今天是您的生日。祝您生日快乐，愿你好上加好，福中更福！";
					//向投资人人发送短信
		    		String re = SmsUtils.send(inves.getMobile(),msg);
		    		LOGGER.info("SmsUtils send investorBirthTask message for investor [{}]result :"+re.toString(),inves.getMobile());
		    		String employeeId = inves.getEmployeeId();
		    		if(employeeId != null){
		    			Employee emp = employeeServiceImpl.get(employeeId);
		    			//保存理财师推送消息
						MessageLog message = new MessageLog();
		 				message.setId(ObjectId.get().toString());
		 				message.setEmployeeId(employeeId);
		 				message.setSender("机构消息");
		 				message.setSource("机构后台");
		 				message.setType(2);
		 				message.setState(0);
		 				message.setSkipType(6);
		 				message.setMessageType(1);
		 				message.setSkipKey(inves.getId());
		 				message.setOrgId(inves.getOrgId());
		 				Date date = new Date();
		 				message.setCreateTime(date);
		 				message.setSendTime(date);
		 				String msgEmp ="今天是您的投资人 "+inves.getName()+" 的生日，请送上您最诚挚的祝福";
		 				message.setMessage(msgEmp);
		 				//保存理财师消息日志
		 				int result = messageLogServiceImpl.save(message);
		 				if(result == 1){
		 					LOGGER.error("save message for employee at investorBirthTask success");
		 				}else{
		 					LOGGER.error("save message for employee at investorBirthTask error");
		 				}
		 				//保存投后APP用户推送消息
		 				Customer customer = new Customer();
		 				customer.setMobile(inves.getMobile());
		 				List<Customer> cusList = customerServiceImpl.pagedList(customer);
		 				if(cusList.size()!=1){
		 					LOGGER.error("save message for customer at investorBirthTask error");
		 				}else{
		 					MessageLog msgLog = new MessageLog();
		 					msgLog.setId(ObjectId.get().toString());
		 					msgLog.setCreateTime(date);
		 					msgLog.setCustomerId(cusList.get(0).getId());
		 					msgLog.setType(3);
		 					msgLog.setBusinessType(1);
		 					msgLog.setMessage(msg);
		 					msgLog.setBusinessType(1);
		 					msgLog.setSource("机构后台");
		 					msgLog.setOrgId(inves.getOrgId());
		 					msgLog.setState(0);
			 				//保存投后用户消息日志
			 				int res = messageLogServiceImpl.save(msgLog);
			 				if(res == 1){
			 					LOGGER.error("save message for customer at investorBirthTask success");
			 				}else{
			 					LOGGER.error("save message for customer at investorBirthTask error");
			 				}
		 				}
		 				//向机构理财师pad端发送投资人生日消息
		     			MessagePush messagePush = new MessagePush(msgEmp,"机构消息");
		     			Set<String> alias = new HashSet<String>();
		     			alias.add(employeeId);
		     			messagePush.sendPushAlias(alias);
		     			//向理财师发送投资人生日提醒短信
			    		String res = SmsUtils.send(emp.getMobile(),msgEmp);
			    		//向投后APP用户发送推送消息  (别名为投后用户id,组别为机构id) 
			    		MessagePush messageCusPush = new MessagePush(msg,"机构消息",messageLogServiceImpl.getUnReadNum(inves.getOrgId(), cusList.get(0).getId()));
		     			messageCusPush.sendCusPushTag(inves.getOrgId(),cusList.get(0).getId());
			    		LOGGER.info("SmsUtils send investorBirthTask message for employee and customer [{}] result :"+res.toString(),emp.getMobile());
			    		//投资人测评时间超过一年,测评状态修改为未测评
						Date evaluationTime = inves.getEvaluationTime();
						int  count = MyDateUtils.countDays(evaluationTime,today);
						if(count >= 365){
							Investor i = new Investor();
							i.setId(inves.getId());
							i.setEvaluaState(4);
							investorServiceImpl.updateById(i);
							LOGGER.info("update  investor  EvaluaState to 4 for param[{}]",i.toString());
						}
		    		}
				}
			}
			return "investorBirthTask execute success";
		} catch (Exception e) {
			e.printStackTrace();
			LOGGER.info("investorBirthTask execute error: "+ e.getMessage());
			return "investorBirthTask execute error";
		}
	}
	
	/**
	 * 定时任务 ：未支付订单生成后72小时内通知理财师提醒投资人付款
	 * 每隔一个小时执行一次
	 */
	public String nonPayOrdersRemindTask(){
		try {
			Orders order = new Orders();
			//获取未支付状态且未删除状态的订单
			order.setState(2);
			order.setDeleted(false);
			List<Orders> list = ordersServiceImpl.pagedList(order);
			for (Orders orders : list) {
				Date orderTime = orders.getOrderTime();//订单生成时间
				Date nowDate = new Date();//当前时间
				//计算订单生成时间距离当前时间相差小时数
				int differ = (new  Double(MyDateUtils.countHours(orderTime,nowDate))).intValue();
				//订单生成时间超过72小时不再提醒
				if(differ > 72){
					continue;
				}
				Integer orderHour = Integer.parseInt(DateFormatUtils.format(orderTime, "HH"));//获取订单生成时间小时数
				Integer curHour = Integer.parseInt(DateFormatUtils.format(nowDate, "HH"));//获取当前时间小时数
				//订单时间在凌晨1点至早晨9点时，提醒时间放在下午17点
				if(orderHour >= 1 && orderHour <= 9 ){
					orderHour = 17;
				}
				//订单时间在下午17点至晚上零点时，提醒时间放在早晨9点
				if(orderHour >= 17 || orderHour == 0 ){
					orderHour = 9;
				}
				//提醒时间与当前时间小时数一致则发送提醒支付通知
				if(orderHour == curHour){
					    String employeeId = orders.getEmployeeId();
						Investor investor = investorServiceImpl.get(orders.getInvestorId());
						Employee emp = employeeServiceImpl.get(employeeId);
						if (investor == null || emp == null) {
							LOGGER.error("save message for nonPayOrdersRemindTask error due to param is not compeletly");
							continue;
						}
		    			//向理财师推送消息
						MessageLog message = new MessageLog();
		 				message.setId(ObjectId.get().toString());
		 				message.setEmployeeId(employeeId);
		 				message.setSender("机构消息");
		 				message.setSource("机构后台");
		 				message.setType(2);
		 				message.setState(0);
		 				message.setMessageType(3);
		 				message.setSkipKey(orders.getOrderId());
		 				message.setSkipType(1);
		 				message.setOrgId(emp.getOrgId());
		 				Date date = new Date();
		 				message.setCreateTime(date);
		 				message.setSendTime(date);
		 				String msgEmp ="您的投资人"+investor.getName()+"购买的"+orders.getProductBriefName()+"产品还未支付，请尽快联系投资人进行洽谈支付";
		 				message.setMessage(msgEmp);
		 				//保存消息日志
		 				int result = messageLogServiceImpl.save(message);
		 				if(result == 1){
		 					LOGGER.error("save message for nonPayOrdersRemindTask success");
		 				}else{
		 					LOGGER.error("save message for nonPayOrdersRemindTask error");
		 					continue;
		 				}
		 				//向机构理财师pad端发送提醒投资人付款消息
		     			MessagePush messagePush = new MessagePush(msgEmp,"机构消息");
		     			Set<String> alias = new HashSet<String>();
		     			alias.add(employeeId);
		     			messagePush.sendPushAlias(alias);
				}
			}
			return "nonPayOrdersRemindTask execute success";
		} catch (Exception e) {
			LOGGER.info("nonPayOrdersRemindTask execute error: "+ e.getMessage());
			return "nonPayOrdersRemi"
					+ ""
					+ "ndTask execute error";
		}
	}
	
	/**
	 * 定时任务: 每天计算更新订单状态-即将到期-待兑付
	 */
	public void ordersStateModifyTask() {
		try {
			List<OrderStateResBean> OrderList = ordersDao.getOrderStateList(new Orders());
			if(OrderList.size() == 0){
				return;
			}
			Iterator<OrderStateResBean> iter = OrderList.iterator();
			List<OrderStateResBean> newOrderList = new ArrayList<OrderStateResBean>();
			while (iter.hasNext()) {
				OrderStateResBean o = iter.next();
				DateTime now = new DateTime();
				DateTime setupDate = new DateTime(o.getSetupTime());
				if(setupDate.plusMonths(o.getDuration()).isBefore(now.plusDays(7))){
					o.setState(STATE_EXPIRE);
					newOrderList.add(o);
				}
				if(setupDate.plusMonths(o.getDuration()).isBefore(now)){
					o.setState(STATE_BECASHED);
					newOrderList.add(o);
				}
			}
			int result = 0;
			if(newOrderList.size() != 0){
				result = ordersDao.updateOrderListState(newOrderList);
			}
			LOGGER.info("本次定时任务更新订单数量为 = [{}]", result);
		} catch (Exception e) {
			LOGGER.error("Timed Task error, error=[{}]", e.getMessage());
		}
	}
	
	/**
     * 获取在当前时间之后的未处理的预约单 
     * @param model 参数
     * @return List<RelationResBean>
     */
	public List<Appointment> unDealList(Appointment appointment) {
		return appointmentDao.unDealList(appointment);
	}
}
